use crate::byte::*;
use crate::huffman::HuffmanTable;
use crate::workspace::WorkSpace;

use super::{error::*, LiteralSectionHeader, JumpTable, stream::LiteralStream};

#[derive(Debug)]
pub struct CompressedLiteralsBlock {
    huffman_table:HuffmanTable,
    jump_table:Option<JumpTable>,
    literal_stream:LiteralStream,
}

impl CompressedLiteralsBlock {
    pub fn serialize_into<W:ByteWrite>(&self, writer:&mut ByteWriter<W>) -> LitResult<()> {
        self.huffman_table.serialize_into(writer)?;
        if let Some(jump_table) = &self.jump_table { jump_table.serialize_into(writer)?; }
        self.literal_stream.serialize_into(writer)?;
        Ok(())
    }

    pub fn deserialize_from(header:&LiteralSectionHeader, raw_data:Vec<u8>, workspace:&mut WorkSpace) -> LitResult<Self> {
        let cosume_bytes_num = workspace.load_huffman_table(&raw_data)?;
        let huffman_table = workspace.huffman_table.as_ref().unwrap().clone();
        let rest_data = &raw_data[cosume_bytes_num..];
        let jump_table = if header.stream_num() == 4 {
            Some(JumpTable::deserialize_from(header, rest_data.len(), &rest_data[0..6], workspace)?)
        } else {
            None
        };
        let stream_data = if jump_table.is_some() {
            &rest_data[6..]
        } else {
            rest_data
        };
        let literal_stream = LiteralStream::deserialize_from(jump_table.as_ref(), stream_data, workspace)?;
        Ok(Self { huffman_table, jump_table, literal_stream })
    }

    pub fn literal_stream(&self) -> &[u8] {
        &self.literal_stream
    }
}